package com.opennews.openplatform.familyexpenseapi.service

import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.opennews.openplatform.familyexpenseapi.dto.app.error.report.AppErrorReportDto
import com.opennews.openplatform.familyexpenseapi.entity.Tables.APP_ERROR_REPORT
import com.opennews.openplatform.myspringbootcore.util.convertCamelToSnake
import jakarta.validation.Valid
import org.jooq.DSLContext
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class AppErrorReportService(
    private val dslContext: DSLContext,
    private val objectMapper: ObjectMapper,
) {
    /**
     * Saves error report sent from the app.
     */
    @Transactional
    fun save(@Valid data: AppErrorReportDto) {
        val mapData = objectMapper.convertValue(data, HashMap::class.java) as MutableMap<String, Any?>

        // If deviceInfo contains a map instance, then we need to convert it to a string type.
        try {
            val json = objectMapper.writeValueAsString(data.deviceInfo)
            mapData["deviceInfo"] = json
        } catch (e: JsonProcessingException) {
            e.printStackTrace()
        }

        // If systemInfo contains a map instance, then we need to convert it to a string type.
        try {
            val json = objectMapper.writeValueAsString(data.systemInfo)
            mapData["systemInfo"] = json
        } catch (e: JsonProcessingException) {
            e.printStackTrace()
        }

        // Converts keys to snake case for database column names since record.formMap() expects key to be the same as column name.
        val convertedMapData = mutableMapOf<String, Any?>()

        mapData.forEach { (key, value) ->
            convertedMapData[convertCamelToSnake(key)] = value
        }

        // Creates a new AppErrorReport with provided data.
        val record = dslContext.newRecord(APP_ERROR_REPORT)
        record.fromMap(convertedMapData)
        record.insert()
    }
}